package cn.shengchao.examstar.knowledge.acl.adapters;

import cn.shengchao.examstar.knowledge.acl.dto.KnowledgePointMasteryDTO;
import cn.shengchao.examstar.knowledge.acl.ports.KnowledgePointMasteryPort;
import cn.shengchao.examstar.knowledge.domain.vo.MasteryStatusEnum;
import cn.shengchao.examstar.shared.application.ai.AiStudyPlanAppService;
import cn.shengchao.examstar.shared.domain.ai.vo.DegreeOfMastery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 学习计划适配器
 * 用于与AI模块的学习计划功能集成，实现知识点掌握度的同步更新
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class StudyPlanAdapter {

    private final AiStudyPlanAppService aiStudyPlanService;
    private final KnowledgePointMasteryPort masteryPort;
    
    /**
     * 根据练习结果更新知识点掌握度
     *
     * @param userId           用户ID
     * @param knowledgePointId 知识点ID
     * @param accuracyRate     正确率
     * @param degreeOfMastery
     * @param studyPlanId      学习计划ID
     * @return 更新后的知识点掌握度
     */
    public KnowledgePointMasteryDTO updateMasteryFromExercise(Long userId, Long knowledgePointId,
                                                              String accuracyRate, String degreeOfMastery, Long studyPlanId) {
        log.info("练习后更新知识点掌握度: 用户ID={}, 知识点ID={}, 正确率={}, 学习计划ID={}", 
                userId, knowledgePointId, accuracyRate, studyPlanId);
        
        // 根据正确率计算掌握度级别
        double percentage = getPercentageFromAccuracyRate(accuracyRate);
        
        // 更新知识点掌握度
        KnowledgePointMasteryDTO mastery = masteryPort.updateKnowledgePointMastery(
            userId, knowledgePointId, degreeOfMastery, accuracyRate, studyPlanId);
        
        // 同步更新学习计划中的掌握度信息（如果学习计划ID不为空）
        if (studyPlanId != null) {
            updateStudyPlanMastery(userId, knowledgePointId, studyPlanId, percentage, degreeOfMastery);
        }
        
        return mastery;
    }
    
    /**
     * 批量更新学习计划中的知识点掌握度
     * 
     * @param studyPlanId 学习计划ID
     * @param userId 用户ID
     * @param knowledgePointMasteryList 知识点掌握度列表
     * @return 更新后的掌握度列表
     */
    public List<KnowledgePointMasteryDTO> batchUpdateMasteryForStudyPlan(
            Long studyPlanId, Long userId, List<KnowledgePointMasteryDTO> knowledgePointMasteryList) {
        
        // 为每个知识点掌握度设置用户ID和学习计划ID
        knowledgePointMasteryList.forEach(masteryDTO -> {
            if (masteryDTO.getUserId() == null) {
                masteryDTO.setUserId(userId);
            }
            if (masteryDTO.getStudyPlanId() == null) {
                masteryDTO.setStudyPlanId(studyPlanId);
            }
        });
        
        // 批量更新掌握度
        List<KnowledgePointMasteryDTO> updatedMasteryList = masteryPort.batchUpdateMastery(knowledgePointMasteryList);
        
        // 更新学习计划中的总体掌握度
        updateStudyPlanMasteryFromKnowledgePoints(studyPlanId, userId, updatedMasteryList);
        
        return updatedMasteryList;
    }
    
    /**
     * 获取学习计划相关的知识点掌握度
     */
    public List<KnowledgePointMasteryDTO> getStudyPlanKnowledgePointMasteries(Long studyPlanId) {
        return masteryPort.getStudyPlanKnowledgePointMasteries(studyPlanId);
    }
    
    /**
     * 更新知识点掌握度状态
     * 
     * @param userId 用户ID
     * @param knowledgePointId 知识点ID
     * @param status 状态枚举
     * @return 更新后的知识点掌握度
     */
    public KnowledgePointMasteryDTO updateMasteryStatus(Long userId, Long knowledgePointId, 
                                                        MasteryStatusEnum status) {
        log.info("更新知识点掌握度状态: 用户ID={}, 知识点ID={}, 状态={}",
                userId, knowledgePointId, status);
        
        // 调用端口更新状态
        return masteryPort.updateKnowledgePointMasteryStatus(userId, knowledgePointId, status);
    }
    
    /**
     * 批量更新知识点掌握度状态
     * 
     * @param userId 用户ID
     * @param knowledgePointIds 知识点ID列表
     * @param status 状态枚举
     * @return 更新后的知识点掌握度列表
     */
    public List<KnowledgePointMasteryDTO> batchUpdateMasteryStatus(Long userId, List<Long> knowledgePointIds,
                                                                 MasteryStatusEnum status) {
        log.info("批量更新知识点掌握度状态: 用户ID={}, 知识点数量={}, 状态={}",
                userId, knowledgePointIds.size(), status);
        
        // 调用端口批量更新状态
        return masteryPort.batchUpdateKnowledgePointMasteryStatus(userId, knowledgePointIds, status);
    }
    
    /**
     * 根据正确率计算掌握度级别
     */
    private String calculateDegreeOfMastery(String accuracyRate) {
        double rate = getPercentageFromAccuracyRate(accuracyRate);
        
        if (rate >= 90) {
            return "S"; // 精通
        } else if (rate >= 75) {
            return "A"; // 掌握
        } else if (rate >= 60) {
            return "B"; // 理解
        } else {
            return "C"; // 初步了解
        }
    }
    
    /**
     * 从正确率字符串中提取百分比值
     */
    private double getPercentageFromAccuracyRate(String accuracyRate) {
        try {
            return Double.parseDouble(accuracyRate.replace("%", ""));
        } catch (Exception e) {
            log.error("解析正确率失败: {}", accuracyRate, e);
            return 0.0;
        }
    }
    
    /**
     * 更新学习计划中的掌握度
     */
    private void updateStudyPlanMastery(Long userId, Long knowledgePointId, Long studyPlanId, double percentage, String degreeCode) {
        try {
            DegreeOfMastery masteryLevel = new DegreeOfMastery(percentage, getDegreeDescription(degreeCode));
            aiStudyPlanService.updateStudyProgress(userId.toString(), knowledgePointId.toString(), masteryLevel);
            log.info("更新学习计划掌握度成功: 学习计划ID={}, 掌握度={}", studyPlanId, degreeCode);
        } catch (Exception e) {
            log.error("更新学习计划掌握度失败: 学习计划ID={}, 掌握度={}", studyPlanId, degreeCode, e);
        }
    }
    
    /**
     * 根据多个知识点掌握度更新学习计划总体掌握度
     */
    private void updateStudyPlanMasteryFromKnowledgePoints(Long studyPlanId, Long userId,
                                                          List<KnowledgePointMasteryDTO> masteryList) {
        if (masteryList == null || masteryList.isEmpty()) {
            return;
        }
        
        // 计算平均掌握度
        double avgPercentage = masteryList.stream()
                .mapToDouble(m -> getPercentageFromAccuracyRate(m.getAccuracyRate()))
                .average()
                .orElse(0.0);
        
        String degreeCode = calculateDegreeFromPercentage(avgPercentage);
        DegreeOfMastery masteryLevel = new DegreeOfMastery(avgPercentage, getDegreeDescription(degreeCode));
        
        // 创建知识点 ID 映射
        Map<String, DegreeOfMastery> masteryLevels = new HashMap<>();
        masteryList.forEach(m -> {
            double percentage = getPercentageFromAccuracyRate(m.getAccuracyRate());
            masteryLevels.put(m.getKnowledgePointId().toString(), 
                new DegreeOfMastery(percentage, getDegreeDescription(m.getDegreeOfMastery())));
        });
        
        try {
            // 生成学习计划
            List<String> knowledgePointIds = masteryList.stream()
                .map(m -> m.getKnowledgePointId().toString())
                .collect(Collectors.toList());
            
            aiStudyPlanService.generateStudyPlan(knowledgePointIds, masteryLevels);
            log.info("更新学习计划总体掌握度成功: studyPlanId={}, avgPercentage={}, degreeCode={}", 
                    studyPlanId, avgPercentage, degreeCode);
        } catch (Exception e) {
            log.error("更新学习计划总体掌握度失败", e);
        }
    }
    
    /**
     * 根据百分比计算掌握度级别
     */
    private String calculateDegreeFromPercentage(double percentage) {
        if (percentage >= 90) {
            return "S"; // 精通
        } else if (percentage >= 75) {
            return "A"; // 掌握
        } else if (percentage >= 60) {
            return "B"; // 理解
        } else {
            return "C"; // 初步了解
        }
    }
    
    /**
     * 获取掌握度描述
     */
    private String getDegreeDescription(String degree) {
        if (degree == null) {
            return "初步了解";
        }
        
        switch (degree.toUpperCase()) {
            case "S": return "精通";
            case "A": return "掌握";
            case "B": return "理解";
            case "C":
            default: return "初步了解";
        }
    }
} 